home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Format 1995 June
/
MacFormat 25.iso
/
Shareware City
/
Developers
/
OutOfPhase1.1 Source
/
OutOfPhase Folder
/
PeepholeOptimizer.c
< prev
next >
Wrap
Text File
|
1994-12-28
|
36KB
|
936 lines
/* PeepholeOptimizer.c */
/*****************************************************************************/
/* */
/* Out Of Phase: Digital Music Synthesis on General Purpose Computers */
/* Copyright (C) 1994 Thomas R. Lawrence */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 2 of the License, or */
/* (at your option) any later version. */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software */
/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* */
/* Thomas R. Lawrence can be reached at tomlaw@world.std.com. */
/* */
/*****************************************************************************/
#include "MiscInfo.h"
#include "Audit.h"
#include "Debug.h"
#include "Definitions.h"
#define SHOW_ME_OPCODEREC /* we need to see the contents of opcode records */
#include "PeepholeOptimizer.h"
#include "PcodeObject.h"
#include "Memory.h"
#include "FixedPoint.h"
#include "FloatingPoint.h"
/* this routine scans the entire code block to see if any branches are made */
/* to any but the first instruction specified in the run of instructions. */
/* Start points to the first instruction, Extent specifies the number of WORDS */
/* (not instructions). Branches MAY point to Prog[Start], however. */
static MyBoolean NoBranchToInterior(OpcodeRec* Prog, long Length,
long Start, long Extent)
{
long Scan;
for (Scan = 0; Scan < Length; Scan += GetInstructionLength(Prog[Scan].Opcode))
{
PRNGCHK(Prog,&(Prog[Scan]),sizeof(Prog[Scan]));
if ((Prog[Scan].Opcode == epBranchUnconditional)
|| (Prog[Scan].Opcode == epBranchIfZero)
|| (Prog[Scan].Opcode == epBranchIfNotZero))
{
/* branch operation detected, test index */
PRNGCHK(Prog,&(Prog[Scan + 1]),sizeof(Prog[Scan + 1]));
if ((Prog[Scan + 1].ImmediateInteger > Start)
&& (Prog[Scan + 1].ImmediateInteger < Start + Extent))
{
/* branch to interior found, so return false. */
return False;
}
}
}
ERROR(Scan != Length,PRERR(ForceAbort,
"NoBranchToInterior: internal instruction alignment error"));
return True;
}
/* this routine eliminates the specified segment of code from the program */
/* and updates all branches pointing to areas beyond it. The new length */
/* is returned. it also disposes of any additional storage used by the */
/* instructions being deleted */
static long DropCodeSegment(OpcodeRec* Prog, long Length,
long Start, long Extent)
{
long Scan;
/* sanity check */
ERROR(!NoBranchToInterior(Prog,Length,Start,Extent),
PRERR(ForceAbort,"DropCodeSegment: branches to interior"));
/* first, patch up branches */
for (Scan = 0; Scan < Length; Scan += GetInstructionLength(Prog[Scan].Opcode))
{
/* looking for branch instructions */
PRNGCHK(Prog,&(Prog[Scan]),sizeof(Prog[Scan]));
if ((Prog[Scan].Opcode == epBranchUnconditional)
|| (Prog[Scan].Opcode == epBranchIfZero)
|| (Prog[Scan].Opcode == epBranchIfNotZero))
{
/* found a branch instruction. does it need to be patched? */
PRNGCHK(Prog,&(Prog[Scan + 1]),sizeof(Prog[Scan + 1]));
if (Prog[Scan + 1].ImmediateInteger > Start)
{
/* branch is beyond segment being dropped, so decrement it's address */
/* by the length of the segment */
Prog[Scan + 1].ImmediateInteger -= Extent;
}
}
}
ERROR(Scan != Length,PRERR(ForceAbort,
"DropCodeSegment: internal instruction alignment error: branch resolve phase"));
/* next, dispose of additional memory owned by the instructions that */
/* are being deleted */
for (Scan = Start; Scan < Start + Extent;
Scan += GetInstructionLength(Prog[Scan].Opcode))
{
switch (Prog[Scan].Opcode)
{
case epFuncCallUnresolved: /* <opcode> ^"<functionname>" ^[paramlist] <returntype> <reserved> */
case epFuncCallResolved: /* <opcode> ^"<functionname>" ^[paramlist] <returntype> ^<OpcodeRec> */
PRNGCHK(Prog,&(Prog[Scan + 1]),sizeof(Prog[Scan + 1]));
ReleasePtr(Prog[Scan + 1].ImmediateString);
PRNGCHK(Prog,&(Prog[Scan + 2]),sizeof(Prog[Scan + 2]));
ReleasePtr((char*)(Prog[Scan + 2].DataTypeArray));
break;
case epOperationBooleanEqual: /* <opcode> */
case epOperationBooleanNotEqual:
case epOperationBooleanAnd:
case epOperationBooleanOr:
case epOperationBooleanNot:
case epOperationBooleanToInteger:
case epOperationBooleanToFloat:
case epOperationBooleanToDouble:
case epOperationBooleanToFixed:
case epOperationIntegerAdd:
case epOperationIntegerSubtract:
case epOperationIntegerNegation:
case epOperationIntegerMultiply:
case epOperationIntegerDivide:
case epOperationIntegerModulo:
case epOperationIntegerShiftLeft:
case epOperationIntegerShiftRight:
case epOperationIntegerGreaterThan:
case epOperationIntegerLessThan:
case epOperationIntegerGreaterThanOrEqual:
case epOperationIntegerLessThanOrEqual:
case epOperationIntegerEqual:
case epOperationIntegerNotEqual:
case epOperationIntegerAbs:
case epOperationIntegerToBoolean:
case epOperationIntegerToFloat:
case epOperationIntegerToDouble:
case epOperationIntegerToFixed:
case epOperationFloatAdd:
case epOperationFloatSubtract:
case epOperationFloatNegation:
case epOperationFloatMultiply:
case epOperationFloatDivide:
case epOperationFloatGreaterThan:
case epOperationFloatLessThan:
case epOperationFloatGreaterThanOrEqual:
case epOperationFloatLessThanOrEqual:
case epOperationFloatEqual:
case epOperationFloatNotEqual:
case epOperationFloatAbs:
case epOperationFloatToBoolean:
case epOperationFloatToInteger:
case epOperationFloatToDouble:
case epOperationFloatToFixed:
case epOperationDoubleAdd:
case epOperationDoubleSubtract:
case epOperationDoubleNegation:
case epOperationDoubleMultiply:
case epOperationDoubleDivide:
case epOperationDoubleGreaterThan:
case epOperationDoubleLessThan:
case epOperationDoubleGreaterThanOrEqual:
case epOperationDoubleLessThanOrEqual:
case epOperationDoubleEqual:
case epOperationDoubleNotEqual:
case epOperationDoubleAbs:
case epOperationDoubleToBoolean:
case epOperationDoubleToInteger:
case epOperationDoubleToFloat:
case epOperationDoubleToFixed:
case epOperationDoubleSin:
case epOperationDoubleCos:
case epOperationDoubleTan:
case epOperationDoubleAtan:
case epOperationDoubleLn:
case epOperationDoubleExp:
case epOperationDoubleSqrt:
case epOperationDoublePower:
case epOperationFixedAdd:
case epOperationFixedSubtract:
case epOperationFixedNegation:
case epOperationFixedMultiply:
case epOperationFixedDivide:
case epOperationFixedShiftLeft:
case epOperationFixedShiftRight:
case epOperationFixedGreaterThan:
case epOperationFixedLessThan:
case epOperationFixedGreaterThanOrEqual:
case epOperationFixedLessThanOrEqual:
case epOperationFixedEqual:
case epOperationFixedNotEqual:
case epOperationFixedAbs:
case epOperationFixedToBoolean:
case epOperationFixedToInteger:
case epOperationFixedToFloat:
case epOperationFixedToDouble:
case epGetBooleanArraySize: /* <opcode> */
case epGetIntegerArraySize:
case epGetFloatArraySize:
case epGetDoubleArraySize:
case epGetFixedArraySize:
case epReturnFromSubroutine: /* <opcode> */
case epLoadImmediateNILArray: /* <opcode> */
case epMakeBooleanArray: /* <opcode> */
case epMakeIntegerArray:
case epMakeFloatArray:
case epMakeDoubleArray:
case epMakeFixedArray:
case epStackPop: /* <opcode> */
case epDuplicate: /* <opcode> */
case epNop: /* <opcode> */
case epStackAllocate: /* <opcode> */
case epResizeBooleanArray2: /* <opcode> */
case epResizeIntegerArray2:
case epResizeFloatArray2:
case epResizeDoubleArray2:
case epResizeFixedArray2:
case epStoreBooleanIntoArray2: /* <opcode> */
case epStoreIntegerIntoArray2:
case epStoreFloatIntoArray2:
case epStoreDoubleIntoArray2:
case epStoreFixedIntoArray2:
case epLoadBooleanFromArray2: /* <opcode> */
case epLoadIntegerFromArray2:
case epLoadFloatFromArray2:
case epLoadDoubleFromArray2:
case epLoadFixedFromArray2:
case epOperationBooleanXor:
case epOperationIntegerAnd:
case epOperationFixedAnd:
case epOperationIntegerOr:
case epOperationFixedOr:
case epOperationIntegerXor:
case epOperationFixedXor:
case epOperationIntegerImpreciseDivide:
case epOperationFloatShiftLeft:
case epOperationDoubleShiftLeft:
case epOperationFloatShiftRight:
case epOperationDoubleShiftRight:
case epOperationIntegerNot:
case epOperationDoubleAsin:
case epOperationDoubleAcos:
case epOperationDoubleSqr:
case epOperationTestIntegerNegative:
case epOperationTestFloatNegative:
case epOperationTestDoubleNegative:
case epOperationTestFixedNegative:
case epOperationGetSignInteger:
case epOperationGetSignFloat:
case epOperationGetSignDouble:
case epOperationGetSignFixed:
case epStackPopMultiple: /* <opcode> <numwords> */
case epStackDeallocateUnder: /* <opcode> <numwords> */
case epOperationBooleanToIntegerBuried: /* <opcode> <stackindex> */
case epOperationBooleanToFloatBuried:
case epOperationBooleanToDoubleBuried:
case epOperationBooleanToFixedBuried:
case epOperationIntegerToBooleanBuried:
case epOperationIntegerToFloatBuried:
case epOperationIntegerToDoubleBuried:
case epOperationIntegerToFixedBuried:
case epOperationFloatToBooleanBuried:
case epOperationFloatToIntegerBuried:
case epOperationFloatToDoubleBuried:
case epOperationFloatToFixedBuried:
case epOperationDoubleToBooleanBuried:
case epOperationDoubleToIntegerBuried:
case epOperationDoubleToFloatBuried:
case epOperationDoubleToFixedBuried:
case epOperationFixedToBooleanBuried:
case epOperationFixedToIntegerBuried:
case epOperationFixedToFloatBuried:
case epOperationFixedToDoubleBuried:
case epBranchUnconditional: /* <opcode> <branchoffset> */
case epBranchIfZero:
case epBranchIfNotZero:
case epStoreIntegerOnStack: /* <opcode> <stackindex> */
case epStoreFloatOnStack:
case epStoreDoubleOnStack:
case epStoreArrayOnStack:
case epLoadIntegerFromStack:
case epLoadFloatFromStack:
case epLoadDoubleFromStack:
case epLoadArrayFromStack:
case epLoadImmediateInteger: /* <opcode> <integer>; also used for boolean & fixed */
break;
case epLoadImmediateFloat: /* <opcode> ^<float> */
PRNGCHK(Prog,&(Prog[Scan + 1]),sizeof(Prog[Scan + 1]));
ReleasePtr((char*)(Prog[Scan + 1].ImmediateFloat));
break;
case epLoadImmediateDouble: /* <opcode> ^<double> */
PRNGCHK(Prog,&(Prog[Scan + 1]),sizeof(Prog[Scan + 1]));
ReleasePtr((char*)(Prog[Scan + 1].ImmediateDouble));
break;
case epGetSampleLeftArray: /* <opcode> ^"<namestring>" */
case epGetSampleRightArray:
case epGetSampleMonoArray:
PRNGCHK(Prog,&(Prog[Scan + 1]),sizeof(Prog[Scan + 1]));
ReleasePtr((char*)(Prog[Scan + 1].ImmediateString));
break;
case epErrorTrap: /* <opcode> ^"<errorstring>" */
PRNGCHK(Prog,&(Prog[Scan + 1]),sizeof(Prog[Scan + 1]));
ReleasePtr(Prog[Scan + 1].ImmediateString);
break;
default:
EXECUTE(PRERR(ForceAbort,"DropCodeSegment: unknown opcode"));
}
}
ERROR(Scan != Start + Extent,PRERR(ForceAbort,
"DropCodeSegment: internal instruction alignment error: dispose phase"));
/* now, delete the code segment */
for (Scan = Start; Scan < Length - Extent; Scan += 1)
{
PRNGCHK(Prog,&(Prog[Scan]),sizeof(Prog[Scan]));
PRNGCHK(Prog,&(Prog[Scan + Extent]),sizeof(Prog[Scan + Extent]));
Prog[Scan] = Prog[Scan + Extent];
}
/* now, erase that little bit at the end */
for (Scan = Length - Extent; Scan < Length; Scan += 1)
{
PRNGCHK(Prog,&(Prog[Scan]),sizeof(Prog[Scan]));
Prog[Scan].Opcode = epNop;
}
/* now, return the new code length */
return Length - Extent;
}
/* this routine looks for indivisible dup/pop operations (with no interior */
/* branches) and eliminates them. *Flag is set if some change was made, and the */
/* new length of Prog[] is returned. */
static long EliminateDupPop(OpcodeRec* Prog, long Length, MyBoolean* Flag)
{
long Scan;
Scan = 0;
while (Scan < Length)
{
/* look to see if this part can be dropped. if it can, we don't increment */
/* Scan so that we can look at the part that will be moved into where this */
/* is as well. otherwise, we do increment */
if ((Prog[Scan].Opcode == epDuplicate)
&& (Prog[Scan + 1].Opcode == epStackPop)
&& NoBranchToInterior(Prog,Length,Scan,2))
{
/* found one! */
Length = DropCodeSegment(Prog,Length,Scan,2);
*Flag = True;
}
else
{
/* increment only if not found */
Scan += GetInstructionLength(Prog[Scan].Opcode);
}
}
ERROR(Scan != Length,PRERR(ForceAbort,
"EliminateDupPop: internal instruction alignment error"));
return Length;
}
/* this routine looks for constant operations that can be eliminated. *Flag is */
/* set if some change was made, and the new length of Prog[] is returned. */
static long FoldConstants(OpcodeRec* Prog, long Length, MyBoolean* Flag)
{
long Scan;
Scan = 0;
while (Scan < Length)
{
MyBoolean DidSomething = False;
/* look to see if this part can be folded. if it can, we don't increment */
/* Scan so that we can look at the part that will be moved into where this */
/* is as well. otherwise, we do increment */
switch (Prog[Scan].Opcode)
{
default:
break;
case epLoadImmediateInteger: /* <opcode> <integer> */
if ((Scan + 2 < Length)
&& NoBranchToInterior(Prog,Length,Scan,3/*at least one extra word*/))
{
switch (Prog[Scan + 2].Opcode)
{
default:
break;
case epOperationBooleanToInteger:
/* no operation, remove */
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
break;
case epOperationIntegerToBoolean:
case epOperationFixedToBoolean:
Prog[Scan + 1].ImmediateInteger =
(Prog[Scan + 1].ImmediateInteger != 0);
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
break;
case epOperationBooleanNot:
Prog[Scan + 1].ImmediateInteger =
!Prog[Scan + 1].ImmediateInteger;
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
break;
case epOperationBooleanToFloat:
case epOperationIntegerToFloat:
{
float* FloatConst;
FloatConst = (float*)AllocPtrCanFail(sizeof(float),"Pcode Float");
if (FloatConst != NIL)
{
/* convert int const to float */
*FloatConst = Prog[Scan + 1].ImmediateInteger;
Prog[Scan + 1].ImmediateFloat = FloatConst;
/* change opcode */
Prog[Scan].Opcode = epLoadImmediateFloat;
/* delete opcode after it */
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
}
}
break;
case epOperationBooleanToDouble:
case epOperationIntegerToDouble:
{
double* DoubleConst;
DoubleConst = (double*)AllocPtrCanFail(sizeof(double),"Pcode Double");
if (DoubleConst != NIL)
{
/* convert int const to float */
*DoubleConst = Prog[Scan + 1].ImmediateInteger;
Prog[Scan + 1].ImmediateDouble = DoubleConst;
/* change opcode */
Prog[Scan].Opcode = epLoadImmediateDouble;
/* delete opcode after it */
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
}
}
break;
case epOperationIntegerNegation:
case epOperationFixedNegation:
Prog[Scan + 1].ImmediateInteger =
- Prog[Scan + 1].ImmediateInteger;
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
break;
case epOperationIntegerAbs:
case epOperationFixedAbs:
if (Prog[Scan + 1].ImmediateInteger < 0)
{
Prog[Scan + 1].ImmediateInteger =
- Prog[Scan + 1].ImmediateInteger;
}
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
break;
case epOperationIntegerToFixed:
case epOperationBooleanToFixed:
Prog[Scan + 1].ImmediateInteger =
int2largefixed(Prog[Scan + 1].ImmediateInteger);
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
break;
case epOperationIntegerNot:
Prog[Scan + 1].ImmediateInteger =
~Prog[Scan + 1].ImmediateInteger;
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
break;
case epOperationTestIntegerNegative:
case epOperationTestFixedNegative:
Prog[Scan + 1].ImmediateInteger =
(Prog[Scan + 1].ImmediateInteger < 0);
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
break;
case epOperationGetSignInteger:
case epOperationGetSignFixed:
if (Prog[Scan + 1].ImmediateInteger < 0)
{
Prog[Scan + 1].ImmediateInteger = -1;
}
else if (Prog[Scan + 1].ImmediateInteger > 0)
{
Prog[Scan + 1].ImmediateInteger = 1;
}
else
{
Prog[Scan + 1].ImmediateInteger = 0;
}
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
break;
case epOperationFixedToInteger:
Prog[Scan + 1].ImmediateInteger
= largefixed2int(Prog[Scan + 1].ImmediateInteger);
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
break;
case epOperationFixedToFloat:
{
float* FloatConst;
FloatConst = (float*)AllocPtrCanFail(sizeof(float),"Pcode Float");
if (FloatConst != NIL)
{
/* convert int const to float */
*FloatConst = largefixed2double(Prog[Scan + 1].ImmediateInteger);
Prog[Scan + 1].ImmediateFloat = FloatConst;
/* change opcode */
Prog[Scan].Opcode = epLoadImmediateFloat;
/* delete opcode after it */
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
}
}
break;
case epOperationFixedToDouble:
{
double* DoubleConst;
DoubleConst = (double*)AllocPtrCanFail(sizeof(double),"Pcode Double");
if (DoubleConst != NIL)
{
/* convert int const to float */
*DoubleConst = largefixed2double(Prog[Scan + 1].ImmediateInteger);
Prog[Scan + 1].ImmediateDouble = DoubleConst;
/* change opcode */
Prog[Scan].Opcode = epLoadImmediateDouble;
/* delete opcode after it */
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
}
}
break;
}
}
break;
case epLoadImmediateFloat: /* <opcode> ^<float> */
if ((Scan + 2 < Length)
&& NoBranchToInterior(Prog,Length,Scan,3/*at least one extra word*/))
{
switch (Prog[Scan + 2].Opcode)
{
default:
break;
case epOperationFloatNegation:
*(Prog[Scan + 1].ImmediateFloat) =
- *(Prog[Scan + 1].ImmediateFloat);
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
break;
case epOperationFloatAbs:
if (*(Prog[Scan + 1].ImmediateFloat) < 0)
{
*(Prog[Scan + 1].ImmediateFloat) =
- *(Prog[Scan + 1].ImmediateFloat);
}
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
break;
case epOperationFloatToBoolean:
{
MyBoolean NewValue;
NewValue = (*(Prog[Scan + 1].ImmediateFloat) != 0);
ReleasePtr((char*)Prog[Scan + 1].ImmediateFloat);
Prog[Scan + 1].ImmediateInteger = NewValue;
Prog[Scan].Opcode = epLoadImmediateInteger;
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
}
break;
case epOperationFloatToInteger:
{
float TempValue;
TempValue = *(Prog[Scan + 1].ImmediateFloat);
ReleasePtr((char*)Prog[Scan + 1].ImmediateFloat);
Prog[Scan + 1].ImmediateInteger = TempValue;
Prog[Scan].Opcode = epLoadImmediateInteger;
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
}
break;
case epOperationFloatToDouble:
{
double* DoubleConst;
DoubleConst = (double*)AllocPtrCanFail(sizeof(double),"Pcode Double");
if (DoubleConst != NIL)
{
/* convert int const to float */
*DoubleConst = *(Prog[Scan + 1].ImmediateFloat);
ReleasePtr((char*)Prog[Scan + 1].ImmediateFloat);
Prog[Scan + 1].ImmediateDouble = DoubleConst;
/* change opcode */
Prog[Scan].Opcode = epLoadImmediateDouble;
/* delete opcode after it */
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
}
}
break;
case epOperationFloatToFixed:
{
float TempValue;
TempValue = *(Prog[Scan + 1].ImmediateFloat);
ReleasePtr((char*)Prog[Scan + 1].ImmediateFloat);
Prog[Scan + 1].ImmediateInteger = double2largefixed(TempValue);
Prog[Scan].Opcode = epLoadImmediateInteger;
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
}
break;
case epOperationGetSignFloat:
{
float TempValue;
TempValue = *(Prog[Scan + 1].ImmediateFloat);
ReleasePtr((char*)Prog[Scan + 1].ImmediateFloat);
if (TempValue < 0)
{
Prog[Scan + 1].ImmediateInteger = -1;
}
else if (TempValue > 0)
{
Prog[Scan + 1].ImmediateInteger = 1;
}
else
{
Prog[Scan + 1].ImmediateInteger = 0;
}
Prog[Scan].Opcode = epLoadImmediateInteger;
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
}
break;
case epOperationTestFloatNegative:
{
float TempValue;
TempValue = *(Prog[Scan + 1].ImmediateFloat);
ReleasePtr((char*)Prog[Scan + 1].ImmediateFloat);
Prog[Scan + 1].ImmediateInteger = (TempValue < 0);
Prog[Scan].Opcode = epLoadImmediateInteger;
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
}
break;
}
}
break;
case epLoadImmediateDouble: /* <opcode> ^<double> */
if ((Scan + 2 < Length)
&& NoBranchToInterior(Prog,Length,Scan,3/*at least one extra word*/))
{
switch (Prog[Scan + 2].Opcode)
{
default:
break;
case epOperationDoubleNegation:
*(Prog[Scan + 1].ImmediateDouble)
= - *(Prog[Scan + 1].ImmediateDouble);
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
break;
case epOperationDoubleAbs:
if (*(Prog[Scan + 1].ImmediateDouble) < 0)
{
*(Prog[Scan + 1].ImmediateDouble)
= - *(Prog[Scan + 1].ImmediateDouble);
}
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
break;
case epOperationDoubleToBoolean:
{
MyBoolean NewValue;
NewValue = (*(Prog[Scan + 1].ImmediateDouble) != 0);
ReleasePtr((char*)Prog[Scan + 1].ImmediateDouble);
Prog[Scan + 1].ImmediateInteger = NewValue;
Prog[Scan].Opcode = epLoadImmediateInteger;
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
}
break;
case epOperationDoubleToInteger:
{
double TempValue;
TempValue = *(Prog[Scan + 1].ImmediateDouble);
ReleasePtr((char*)Prog[Scan + 1].ImmediateDouble);
Prog[Scan + 1].ImmediateInteger = TempValue;
Prog[Scan].Opcode = epLoadImmediateInteger;
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
}
break;
case epOperationDoubleToFloat:
{
float* FloatConst;
FloatConst = (float*)AllocPtrCanFail(sizeof(float),"Pcode Float");
if (FloatConst != NIL)
{
/* convert int const to float */
*FloatConst = *(Prog[Scan + 1].ImmediateDouble);
ReleasePtr((char*)Prog[Scan + 1].ImmediateDouble);
Prog[Scan + 1].ImmediateFloat = FloatConst;
/* change opcode */
Prog[Scan].Opcode = epLoadImmediateFloat;
/* delete opcode after it */
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
}
}
break;
case epOperationDoubleToFixed:
{
double TempValue;
TempValue = *(Prog[Scan + 1].ImmediateDouble);
ReleasePtr((char*)Prog[Scan + 1].ImmediateDouble);
Prog[Scan + 1].ImmediateInteger = double2largefixed(TempValue);
Prog[Scan].Opcode = epLoadImmediateInteger;
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
}
break;
case epOperationDoubleSin:
*(Prog[Scan + 1].ImmediateDouble)
= DSIN(*(Prog[Scan + 1].ImmediateDouble));
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
break;
case epOperationDoubleCos:
*(Prog[Scan + 1].ImmediateDouble)
= DCOS(*(Prog[Scan + 1].ImmediateDouble));
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
break;
case epOperationDoubleTan:
*(Prog[Scan + 1].ImmediateDouble)
= DTAN(*(Prog[Scan + 1].ImmediateDouble));
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
break;
case epOperationDoubleAsin:
*(Prog[Scan + 1].ImmediateDouble)
= DASIN(*(Prog[Scan + 1].ImmediateDouble));
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
break;
case epOperationDoubleAcos:
*(Prog[Scan + 1].ImmediateDouble)
= DACOS(*(Prog[Scan + 1].ImmediateDouble));
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
break;
case epOperationDoubleAtan:
*(Prog[Scan + 1].ImmediateDouble)
= DATAN(*(Prog[Scan + 1].ImmediateDouble));
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
break;
case epOperationDoubleLn:
*(Prog[Scan + 1].ImmediateDouble)
= DLN(*(Prog[Scan + 1].ImmediateDouble));
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
break;
case epOperationDoubleExp:
*(Prog[Scan + 1].ImmediateDouble)
= DEXP(*(Prog[Scan + 1].ImmediateDouble));
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
break;
case epOperationDoubleSqrt:
*(Prog[Scan + 1].ImmediateDouble)
= DSQRT(*(Prog[Scan + 1].ImmediateDouble));
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
break;
case epOperationDoubleSqr:
*(Prog[Scan + 1].ImmediateDouble)
= (*(Prog[Scan + 1].ImmediateDouble))
* (*(Prog[Scan + 1].ImmediateDouble));
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
break;
case epOperationTestDoubleNegative:
{
double TempValue;
TempValue = *(Prog[Scan + 1].ImmediateDouble);
ReleasePtr((char*)Prog[Scan + 1].ImmediateDouble);
Prog[Scan + 1].ImmediateInteger = (TempValue < 0);
Prog[Scan].Opcode = epLoadImmediateInteger;
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
}
break;
case epOperationGetSignDouble:
{
double TempValue;
TempValue = *(Prog[Scan + 1].ImmediateDouble);
ReleasePtr((char*)Prog[Scan + 1].ImmediateDouble);
if (TempValue < 0)
{
Prog[Scan + 1].ImmediateInteger = -1;
}
else if (TempValue > 0)
{
Prog[Scan + 1].ImmediateInteger = 1;
}
else
{
Prog[Scan + 1].ImmediateInteger = 0;
}
Prog[Scan].Opcode = epLoadImmediateInteger;
Length = DropCodeSegment(Prog,Length,Scan + 2,1);
DidSomething = True;
*Flag = True;
}
break;
}
}
break;
}
if (!DidSomething)
{
/* increment only if not found */
Scan += GetInstructionLength(Prog[Scan].Opcode);
}
}
ERROR(Scan != Length,PRERR(ForceAbort,
"FoldConstants: internal instruction alignment error"));
return Length;
}
/* perform the optimizations */
void OptimizePcode(PcodeRec* ThePcode)
{
OpcodeRec* Prog;
long Length;
MyBoolean OptimizationFound;
/* obtain the important information */
Prog = GetOpcodeFromPcode(ThePcode);
Length = GetNumberOfValidCellsInPcode(ThePcode);
/* begin the optimization loop */
do
{
/* we go until no more optimizations can be found, so we clear this */
/* flag. at the end, if the flag is set, we'll check again. */
OptimizationFound = False;
Length = EliminateDupPop(Prog,Length,&OptimizationFound);
Length = FoldConstants(Prog,Length,&OptimizationFound);
} while (OptimizationFound);
/* resize the code block to eliminate any empty cells at the end */
if (PtrSize((char*)Prog) != Length * sizeof(OpcodeRec))
{
OpcodeRec* Temp;
Temp = (OpcodeRec*)ResizePtr((char*)Prog,Length * sizeof(OpcodeRec));
if (Temp != NIL)
{
UpdateOpcodeInPcode(ThePcode,Temp,Length);
}
/* if we couldn't resize it, then it's just too bad. the evaluator */
/* doesn't really depend on the length of the opcode for anything, so */
/* it doesn't matter. (DisposePcode does, but the end is erased with */
/* nops, so it shouldn't delete anything important.) */
}
}